# -*- coding: utf-8 -*-
# Author   : ZhangQing
# Time     : 2025-08-05 23:06
# File     : log_utils.py
# Project  : codebuddy_craft
# Desc     : 日志工具模块

# backend/utils/log_utils.py
"""
日志工具模块

提供日志相关的实用工具和中间件
"""

from fastapi import Request, Response
from fastapi.middleware.base import BaseHTTPMiddleware
from starlette.types import ASGIApp
import time
import uuid
from typing import Callable, Optional
import json

from .logger import get_logger, log_api_request


class RequestLoggingMiddleware(BaseHTTPMiddleware):
    """请求日志中间件"""

    def __init__(self, app: ASGIApp, logger_name: str = "api"):
        super().__init__(app)
        self.logger = get_logger(logger_name)

    async def dispatch(self, request: Request, call_next: Callable) -> Response:
        # 生成请求ID
        request_id = str(uuid.uuid4())

        # 记录请求开始
        start_time = time.time()

        # 获取客户端信息
        client_ip = request.client.host if request.client else "unknown"
        user_agent = request.headers.get("user-agent", "unknown")

        # 记录请求详情
        self.logger.info(
            f"📝 API请求开始: {request.method} {request.url.path}",
            extra={
                'extra_fields': {
                    'request_id': request_id,
                    'method': request.method,
                    'path': request.url.path,
                    'query_params': str(request.query_params),
                    'client_ip': client_ip,
                    'user_agent': user_agent,
                    'content_type': request.headers.get("content-type"),
                    'content_length': request.headers.get("content-length")
                }
            }
        )

        # 将请求ID添加到请求状态
        request.state.request_id = request_id

        try:
            # 处理请求
            response = await call_next(request)

            # 计算响应时间
            process_time = time.time() - start_time

            # 记录响应
            self.logger.info(
                f"✅ API请求完成: {request.method} {request.url.path} - {response.status_code} ({process_time:.3f}s)",
                extra={
                    'extra_fields': {
                        'request_id': request_id,
                        'status_code': response.status_code,
                        'response_time': process_time,
                        'response_size': response.headers.get("content-length")
                    }
                }
            )

            # 添加响应头
            response.headers["X-Request-ID"] = request_id
            response.headers["X-Process-Time"] = str(process_time)

            return response

        except Exception as e:
            # 计算错误响应时间
            process_time = time.time() - start_time

            # 记录错误
            self.logger.error(
                f"❌ API请求失败: {request.method} {request.url.path} - {str(e)} ({process_time:.3f}s)",
                exc_info=True,
                extra={
                    'extra_fields': {
                        'request_id': request_id,
                        'error': str(e),
                        'response_time': process_time
                    }
                }
            )

            raise


class WebSocketLoggingMixin:
    """WebSocket日志混入类"""

    def __init__(self):
        self.logger = get_logger(f"websocket.{self.__class__.__name__}")

    def log_connection(self, client_id: str, user_id: str = None):
        """记录WebSocket连接"""
        self.logger.info(
            f"🔌 WebSocket连接建立: {client_id}",
            extra={
                'extra_fields': {
                    'client_id': client_id,
                    'user_id': user_id,
                    'event_type': 'websocket_connect'
                }
            }
        )

    def log_disconnection(self, client_id: str, reason: str = None):
        """记录WebSocket断开连接"""
        self.logger.info(
            f"🔌 WebSocket连接断开: {client_id}",
            extra={
                'extra_fields': {
                    'client_id': client_id,
                    'reason': reason,
                    'event_type': 'websocket_disconnect'
                }
            }
        )

    def log_message(self, client_id: str, message_type: str, data_size: int = None):
        """记录WebSocket消息"""
        self.logger.debug(
            f"📨 WebSocket消息: {client_id} - {message_type}",
            extra={
                'extra_fields': {
                    'client_id': client_id,
                    'message_type': message_type,
                    'data_size': data_size,
                    'event_type': 'websocket_message'
                }
            }
        )

    def log_error(self, client_id: str, error: Exception):
        """记录WebSocket错误"""
        self.logger.error(
            f"❌ WebSocket错误: {client_id} - {str(error)}",
            exc_info=True,
            extra={
                'extra_fields': {
                    'client_id': client_id,
                    'error': str(error),
                    'event_type': 'websocket_error'
                }
            }
        )


class DatabaseLoggingMixin:
    """数据库日志混入类"""

    def __init__(self):
        self.logger = get_logger(f"database.{self.__class__.__name__}")

    def log_query(self, operation: str, table: str, duration: float = None):
        """记录数据库查询"""
        self.logger.debug(
            f"🗄️ 数据库操作: {operation} {table}",
            extra={
                'extra_fields': {
                    'operation': operation,
                    'table': table,
                    'duration': duration,
                    'event_type': 'database_query'
                }
            }
        )

    def log_transaction(self, operation: str, affected_rows: int = None):
        """记录数据库事务"""
        self.logger.info(
            f"🔄 数据库事务: {operation}",
            extra={
                'extra_fields': {
                    'operation': operation,
                    'affected_rows': affected_rows,
                    'event_type': 'database_transaction'
                }
            }
        )

    def log_migration(self, version: str, operation: str, success: bool = True):
        """记录数据库迁移"""
        status = "✅ 成功" if success else "❌ 失败"
        self.logger.info(
            f"🔧 数据库迁移: {version} {operation} - {status}",
            extra={
                'extra_fields': {
                    'version': version,
                    'operation': operation,
                    'success': success,
                    'event_type': 'database_migration'
                }
            }
        )


class LLMLoggingMixin:
    """LLM日志混入类"""

    def __init__(self):
        self.logger = get_logger(f"llm.{self.__class__.__name__}")

    def log_request(self,
                    provider: str,
                    model: str,
                    prompt_tokens: int = None,
                    max_tokens: int = None):
        """记录LLM请求"""
        self.logger.info(
            f"🤖 LLM请求: {provider}/{model}",
            extra={
                'extra_fields': {
                    'provider': provider,
                    'model': model,
                    'prompt_tokens': prompt_tokens,
                    'max_tokens': max_tokens,
                    'event_type': 'llm_request'
                }
            }
        )

    def log_response(self,
                     provider: str,
                     model: str,
                     completion_tokens: int = None,
                     total_tokens: int = None,
                     duration: float = None):
        """记录LLM响应"""
        self.logger.info(
            f"✨ LLM响应: {provider}/{model} ({duration:.2f}s)",
            extra={
                'extra_fields': {
                    'provider': provider,
                    'model': model,
                    'completion_tokens': completion_tokens,
                    'total_tokens': total_tokens,
                    'duration': duration,
                    'event_type': 'llm_response'
                }
            }
        )

    def log_error(self, provider: str, model: str, error: Exception):
        """记录LLM错误"""
        self.logger.error(
            f"💥 LLM错误: {provider}/{model} - {str(error)}",
            exc_info=True,
            extra={
                'extra_fields': {
                    'provider': provider,
                    'model': model,
                    'error': str(error),
                    'event_type': 'llm_error'
                }
            }
        )


# 安全日志函数
def log_security_event(event_type: str,
                       user_id: str = None,
                       ip_address: str = None,
                       details: dict = None):
    """记录安全事件"""
    security_logger = get_logger("security")

    log_data = {
        'event_type': event_type,
        'user_id': user_id,
        'ip_address': ip_address,
        'timestamp': time.time()
    }

    if details:
        log_data.update(details)

    security_logger.warning(
        f"🔒 安全事件: {event_type}",
        extra={'extra_fields': log_data}
    )


# 业务日志函数
def log_business_event(event_type: str,
                       user_id: str = None,
                       project_id: str = None,
                       details: dict = None):
    """记录业务事件"""
    business_logger = get_logger("business")

    log_data = {
        'event_type': event_type,
        'user_id': user_id,
        'project_id': project_id,
        'timestamp': time.time()
    }

    if details:
        log_data.update(details)

    business_logger.info(
        f"📊 业务事件: {event_type}",
        extra={'extra_fields': log_data}
    )


# 性能监控函数
def log_performance_metric(metric_name: str,
                           value: float,
                           unit: str = "ms",
                           tags: dict = None):
    """记录性能指标"""
    perf_logger = get_logger("performance")

    log_data = {
        'metric_name': metric_name,
        'value': value,
        'unit': unit,
        'timestamp': time.time()
    }

    if tags:
        log_data['tags'] = tags

    perf_logger.info(f"📈 性能指标: {metric_name}={value}{unit}")


# 导出所有功能
__all__ = [
    'RequestLoggingMiddleware',
    'WebSocketLoggingMixin',
    'DatabaseLoggingMixin',
    'LLMLoggingMixin',
    'log_security_event',
    'log_business_event',
    'log_performance_metric'
]

